#include "app_device.h"
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include "log/log.h"
#include "app_pool.h"
#include <sys/types.h>
#include <stdint.h>
#include "app_router.h"

/**
 * @brief:设备写任务，负责将写缓存中的数据写入到设备硬件中
 *
 * @param arg 传入的设备指针
 */
static void app_device_writeTask(void *arg)
{
    // 1.从缓冲中读取要写入的设备
    Device *dev = arg;
    uint8_t buf[1024];
    if (app_buffer_read(dev->output_buffer, buf, 3) < 0)
    {
        log_error("Message read fail from device output buffer");
        return;
    }
    if (app_buffer_read(dev->output_buffer, buf + 3, buf[1] + buf[2]) < 0)
    {
        log_error("Message data is incomplete");
        return;
    }
    size_t write_len = buf[1] + buf[2] + 3;

    // 2. TODO:经过兼容层的后处理，目前暂时留空

    // 3.将数据写入设备硬件
    if (write(dev->fd, buf, write_len) < 0)
    {
        log_error("Failed to write data to device");
    }
}

/**
 * @brief:设备发送任务
 *
 * @param arg 传入的设备指针
 */
static void app_device_sendTask(void *arg)
{
    Device *dev = arg;
    // 1.从缓冲中读取数据
    uint8_t buf[1024];
    /** 消息是由二进制组成，帧格式为：
     *   1. 消息类型，1字节
     *   2. 消息ID的长度，1字节
     *   3. 消息内容的长度，1字节
     *   4. 消息ID，二进制，长度可变
     *   5. 消息内容，二进制，长度可变
     */
    if (app_buffer_read(dev->input_buffer, buf, 3) < 0)
    {
        log_error("Failed to read data from device input buffer");
        return;
    }

    if (app_buffer_read(dev->input_buffer, buf + 3, buf[1] + buf[2]) < 0)
    {
        log_error("Message data is incomplete");
        return;
    }

    // 2.将数据交给消息路由
    // TODO：添加处理函数
    app_router_devToMqtt(dev, buf, buf[1] + buf[2] + 3);
}

/**
 * @brief:设备读线程，负责将设备数据写入缓存
 *
 * @param arg 传入的设备指针
 * @return void* 返回NULL
 */
static void *app_device_readThread(void *arg)
{
    uint8_t buf[1024];
    Device *dev = arg;
    while (1)
    {
        // 1.从设备中读取数据
        size_t read_len = read(dev->fd, buf, sizeof(buf));
        // 对数据进行二次处理（这里需要调用蓝牙兼容层的处理函数，目前还没实现，暂时留空）
        // TODO:添加处理函数
        // 写入读缓存
        if (app_buffer_write(dev->input_buffer, buf, read_len) < 0)
        {
            log_error("Failed to write data to device input buffer");
        }
        // 向线程池注册发送任务
        if (app_pool_submit(app_device_sendTask, dev) < 0)
        {
            log_error("Failed to submit send task to pool");
        }
    }
    return NULL;
}

/**
 * @brief:初始化设备
 */

Device *app_device_init(char *dev_name)
{
    // 1.打开设备
    Device *result = malloc(sizeof(Device));
    if (!result)
    {
        log_error("Not_enough_memory for device object");
        goto DEVICE_ALLOC_FAIL;
    }
    memset(result, 0, sizeof(Device));

    // result->name = strdup(dev_name);
    char *copy = NULL;
    if (dev_name != NULL)
    {
        size_t len = strlen(dev_name) + 1; // 包括终止符 '\0'
        copy = malloc(len);
        if (copy != NULL)
        {
            memcpy(copy, dev_name, len);
        }
    }
    result->name = copy;
    
    if (!result->name)
    {
        log_error("Not_enough_memory for device name");
        goto DEVICE_NAME_ALLOC_FAIL;
    }

    result->fd = open(dev_name, O_RDWR);
    if (result->fd < 0)
    {
        log_error("open device %s failed", dev_name);
        goto DEVICE_OPEN_FAIL;
    }

    // 2.初始化设备缓存
    result->input_buffer = app_buffer_init(64 * 1024);
    if (!result->input_buffer)
    {
        log_error("Not_enough_memory for device input buffer");
        goto DEVICE_INPUT_BUFFER_ALLOC_FAIL;
    }
    result->output_buffer = app_buffer_init(64 * 1024);
    if (!result->output_buffer)
    {
        log_error("Not_enough_memory for device output buffer");
        goto DEVICE_OUTPUT_BUFFER_ALLOC_FAIL;
    }

    result->type = TYPE_NONE;

    log_info("device %s init success", dev_name);

    return result;
DEVICE_OUTPUT_BUFFER_ALLOC_FAIL:
    app_buffer_free(result->input_buffer);
DEVICE_INPUT_BUFFER_ALLOC_FAIL:
    close(result->fd);
DEVICE_OPEN_FAIL:
    free(result->name);
DEVICE_NAME_ALLOC_FAIL:
    free(result);
DEVICE_ALLOC_FAIL:
    return NULL;
}

int app_device_start(Device *dev)
{
    // 1.启动设备的后台进程
    if (dev->read_thread)
    {
        // 设备已经启动
        log_warn("device %s has already started", dev->name);
        return -1;
    }
    int ret = pthread_create(&dev->read_thread, NULL, app_device_readThread, dev);
    if (ret < 0)
    {
        log_error("Failed to create device %s read thread", dev->name);
        return -1;
    }
    log_info("device %s start success", dev->name);
    return 0;
}

int app_device_stop(Device *dev)
{
    // 1.关闭设备的后台进程
    if (!dev->read_thread)
    {
        // 设备没有启动
        log_warn("device %s not started", dev->name);
        return -1;
    }
    int ret = pthread_cancel(dev->read_thread);
    if (ret < 0)
    {
        log_error("Failed to cancel device %s read thread", dev->name);
        return -1;
    }
    ret = pthread_join(dev->read_thread, NULL);
    if (ret < 0)
    {
        log_error("Failed to join device %s read thread", dev->name);
        return -1;
    }
    dev->read_thread = 0;
    log_info("device %s stopped", dev->name);
    return 0;
}

void app_device_deinit(Device *dev)
{
    // 1.销毁缓存
    app_buffer_free(dev->input_buffer);
    app_buffer_free(dev->output_buffer);

    // 2.关闭设备
    int ret = close(dev->fd);
    if (ret < 0)
    {
        log_error("Failed to close device %s", dev->name);
    }

    // 3.释放设备对象
    free(dev->name);
    free(dev);
}

int app_device_write(Device *dev, void *data, size_t len)
{
    // 1.将数据写入写缓存
    if (app_buffer_write(dev->output_buffer, data, len) < 0)
    {
        log_error("Failed to write data to device output buffer");
        return -1;
    }
    // 2. 注册设备写任务
    if (app_pool_submit(app_device_writeTask, dev) < 0)
    {
        log_error("Failed to submit device write task");
        return -1;
    }

    return 0;
}
